package com.xplay.xpocker.service.mahjong.impl;

import com.xplay.xpocker.meta.realize.MahjongRoomEntity;
import com.xplay.xpocker.meta.room.MetaRoomEntity;
import com.xplay.xpocker.entity.mahjong.*;
import com.xplay.xpocker.meta.realize.MahjongRule;
import com.xplay.xpocker.meta.realize.MahjongUserChannel;
import com.xplay.xpocker.meta.user.MetaUserChannel;
import com.xplay.xpocker.service.mahjong.IDiskPartService;
import com.xplay.xpocker.util.Assertion;
import com.xplay.xpocker.util.CardUtil;
import com.xplay.xpocker.util.DictionaryConst;
import com.xplay.xpocker.util.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author wanjie
 * @date 2021/3/23 13:05
 */
@Service
public class DiskPartServiceImpl implements IDiskPartService {

    private static Logger log = LoggerFactory.getLogger(DiskPartServiceImpl.class);
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private WzScoringServiceImpl wzScoringService;

    @Override
    public MahjongRoomEntity getRoomInfo(String code) {
        MetaRoomEntity<MahjongRoomEntity, MahjongRule, MahjongUserChannel> roomObject = (MetaRoomEntity<MahjongRoomEntity, MahjongRule, MahjongUserChannel>) redisUtil.get(DictionaryConst.RedisHeader.ROOM_HEADER + code);
        if (roomObject != null && roomObject instanceof MahjongRoomEntity) {
            return (MahjongRoomEntity) roomObject;
        } else if (roomObject != null) {
            return roomObject.getRoomInfo(MahjongRoomEntity.class);
        }
        return null;
    }

    /**
     * @param size     发几张牌
     * @param roomInfo 房间信息
     * @return
     */

    @Override
    public List<Integer> licensingCard(int size, MahjongRoomEntity roomInfo, String userId) {
        List<Integer> result = new ArrayList<>();
        CopyOnWriteArrayList<Integer> allCard = roomInfo.getAllCard();
        Integer allCardSize = allCard.size();
        HashMap<String, CopyOnWriteArrayList<Integer>> allUserCards = roomInfo.getUserCards();
        if (allUserCards == null) {
            allUserCards = new HashMap<String, CopyOnWriteArrayList<Integer>>();
            roomInfo.setUserCards(allUserCards);
        }
        CopyOnWriteArrayList<Integer> userCards = allUserCards.get(userId);
        if (userCards == null) {
            userCards = new CopyOnWriteArrayList<Integer>();
            allUserCards.put(userId, userCards);
        }
        int tag = 0;
        for (int i = allCardSize - 1; i >= 0 && tag < size; i--) {
            Integer cardId = allCard.get(i);
            userCards.add(cardId);
            result.add(cardId);
            allCard.remove(i);
            tag++;
        }
        return result;
    }


    @Override
    public MahjongUserTask userHasTask(MahjongRoomEntity roomInfo, String userId, String action) {
        MahjongUserTask result = null;
        ArrayList<MahjongUserTask> rediRoomTask = roomInfo.getRoomTask();
        if (rediRoomTask != null) {
            Iterator<MahjongUserTask> iterator = rediRoomTask.iterator();
            while (iterator.hasNext()) {
                MahjongUserTask mahjongUserTask = iterator.next();
                if (mahjongUserTask.getTaskArray() != null) {
                    Iterator<String> taskArrayIter = mahjongUserTask.getTaskArray().iterator();
                    while (taskArrayIter.hasNext()) {
                        String aTask = taskArrayIter.next();
                        if (aTask.equals(action) && mahjongUserTask.getUserId().equals(userId)) {
                            result = mahjongUserTask;
                            break;
                        }
                    }
                } else if (mahjongUserTask.getTask() != null && mahjongUserTask.getTask().equals(action) && mahjongUserTask.getUserId().equals(userId)) {
                    result = mahjongUserTask;
                    break;
                }
            }
        }
        return result;
    }

    @Override
    public boolean removeTask(MahjongRoomEntity roomInfo, String userId) {
        ArrayList<MahjongUserTask> rediRoomTask = roomInfo.getRoomTask();
        if (rediRoomTask != null) {
            Iterator<MahjongUserTask> iterator = rediRoomTask.iterator();
            while (iterator.hasNext()) {
                MahjongUserTask mahjongUserTask = iterator.next();
                if (mahjongUserTask.isRemoveTag() && mahjongUserTask.isDealWith() && mahjongUserTask.getTaskArray() != null && mahjongUserTask.getUserId().equals(userId)) {
                    iterator.remove();
                } else if (mahjongUserTask.isRemoveTag() && mahjongUserTask.isDealWith() && mahjongUserTask.getTask() != null && mahjongUserTask.getUserId().equals(userId)) {
                    iterator.remove();
                }
            }
        }
        return true;
    }



    @Override
    public boolean saveRoom(MahjongRoomEntity roomEntity) {
        redisUtil.set(DictionaryConst.RedisHeader.ROOM_HEADER + roomEntity.getCode(), roomEntity,DictionaryConst.RedisExpireData.ROOM_EXPIRE);
        return true;
    }


    /**
     * 从用户的手牌中移除 相应的牌
     *
     * @param userCards
     * @param outCards
     */
    public void removeCard(CopyOnWriteArrayList<Integer> userCards, CopyOnWriteArrayList<Integer> outCards) {
        for (Integer inCard : outCards) {
            int userCardSize = userCards.size();
            for (int i = userCardSize - 1; i >= 0; i--) {
                if (userCards.get(i) == inCard) {
                    userCards.remove(i);
                    break;
                }
            }
        }

    }

    /**
     * 将用户的手牌移除
     * 并且将牌添加到用户出牌的集合中
     *
     * @param exportCard
     * @param roomInfo
     * @param userId
     */

    @Override
    public void exportCard(Integer exportCard, MahjongRoomEntity roomInfo, String userId) {
        HashMap<String, CopyOnWriteArrayList<Integer>> allCards = roomInfo.getUserCards();
        CopyOnWriteArrayList<Integer> userCards = allCards.get(userId);
        Assertion.isTrue("非法操作", !userCards.contains(exportCard));
        CardUtil.removeCard(userCards, exportCard);
        HashMap<String, CopyOnWriteArrayList<Integer>> cards = roomInfo.getUserExportCards();
        if (cards == null) {
            cards = new HashMap<String, CopyOnWriteArrayList<Integer>>();
            roomInfo.setUserExportCards(cards);
        }
        CopyOnWriteArrayList<Integer> userExportCards = cards.get(userId);
        if (null == userExportCards) {
            userExportCards = new CopyOnWriteArrayList<Integer>();
            cards.put(userId, userExportCards);
        }
        userExportCards.add(exportCard);
    }


    @Override
    public void touchCard(MahjongRoomEntity roomInfo, MetaUserChannel userChannel) {
        Integer prevExportCard = roomInfo.getCurrentExportCard();
        String currentExportUserId = roomInfo.getCurrentExportUserId();
        // 将玩家出的牌移除
        CardUtil.removeCard(roomInfo.getUserExportCards().get(currentExportUserId), prevExportCard);
        ArrayList<MahjongCardTouchBar> barCards = roomInfo.getUserTouchBarCards(userChannel.getUserId());
        // 将用户的手牌移除
        CardUtil.removeCard(roomInfo.getUserCards().get(userChannel.getUserId()), Arrays.asList(new Integer[]{prevExportCard, prevExportCard}));
        barCards.add(new MahjongCardTouchBar(currentExportUserId, CardEnum.TOUCH, new ArrayList<>(Arrays.asList(new Integer[]{prevExportCard, prevExportCard, prevExportCard}))));
    }


    @Override
    public MahjongCardBarEntity barCard(MahjongRoomEntity roomInfo, MetaUserChannel userChannel, Integer cardId, Boolean doAction) {
        Integer prevExportCard = roomInfo.getCurrentExportCard();
        CopyOnWriteArrayList<Integer> userCards = roomInfo.getUserCards().get(userChannel.getUserId());
        ArrayList<MahjongCardTouchBar> barCards = roomInfo.getUserTouchBarCards(userChannel.getUserId());
        // 当前出牌的用户
        String currentExportUserId = roomInfo.getCurrentExportUserId();
        if (!currentExportUserId.equals(userChannel.getUserId())) {
            if (doAction) {
                // 这种情况是别人放的杠牌
                // 将玩家出的牌移除
                CardUtil.removeCard(roomInfo.getUserExportCards().get(currentExportUserId), prevExportCard);
                CardUtil.removeCard(userCards, Arrays.asList(new Integer[]{prevExportCard, prevExportCard, prevExportCard}));
                barCards.add(new MahjongCardTouchBar(currentExportUserId, CardEnum.DIANGANG, new ArrayList<>(Arrays.asList(new Integer[]{prevExportCard, prevExportCard, prevExportCard, prevExportCard}))));
                wzScoringService.cardBar(roomInfo, roomInfo.checkFistAndLastFour(), userChannel.getUserId(), CardEnum.DIANGANG);
            }
            return new MahjongCardBarEntity(CardEnum.DIANGANG, prevExportCard);
        } else {

            // 这种情况是自己摸的杠牌
            // 先判断手牌是否有4张
            // 这种情况为暗杠
            if (cardId == null) {
                // 当用户没有选牌的时候 在手中取出
                List<Integer> userBarCards = CardUtil.checkCardNumber(userCards, 4);
                Integer baGangCount = 0;
                ArrayList<Integer> userAllTouchBarCards = roomInfo.getUserAllTouchBarCards(userChannel.getUserId());
                if (null != userAllTouchBarCards && userAllTouchBarCards.size() > 0) {
                    for (Integer cardTemp : userCards) {
                        if (Collections.frequency(userAllTouchBarCards, cardTemp) == 3) {
                            cardId = cardTemp;
                            baGangCount++;
                        }
                    }
                }
                Assertion.isTrue("请选择杠牌", (userBarCards.size() + baGangCount) > 1);
                if (baGangCount == 0) {
                    cardId = userBarCards.get(0);
                }
            }
            // 当从手中取出来还是空的话 就判断巴杠了

            roomInfo.getUserTask(userChannel.getUserId()).setCardId(cardId);
            int cardCount = Collections.frequency(userCards, cardId);
            if (cardCount == 4) {
                if (doAction) {
                    CardUtil.removeCard(userCards, Arrays.asList(new Integer[]{cardId, cardId, cardId, cardId}));
                    barCards.add(new MahjongCardTouchBar(currentExportUserId, CardEnum.ANGANG, new ArrayList<>(Arrays.asList(new Integer[]{cardId, cardId, cardId, cardId}))));
                    wzScoringService.cardBar(roomInfo, roomInfo.checkFistAndLastFour(), userChannel.getUserId(), CardEnum.ANGANG);
                }
                return new MahjongCardBarEntity(CardEnum.ANGANG, cardId);
            }
            // 这种情况为巴杠
            int cardTouchBarCount = Collections.frequency(roomInfo.getUserAllTouchBarCards(userChannel.getUserId()), cardId);
            if (cardTouchBarCount == 3) {
                if (doAction) {
                    // 移除摸得牌
                    CardUtil.removeCard(userCards, cardId);
                    // 添加到碰牌队列中
                    MahjongCardTouchBar touchBar = roomInfo.getUserTouchBarByCardId(userChannel.getUserId(), cardId);
                    touchBar.getCards().add(cardId);
                    touchBar.setCardEnum(CardEnum.MINGGANG);
                    touchBar.setUserId(userChannel.getUserId());
                    wzScoringService.cardBar(roomInfo, roomInfo.checkFistAndLastFour(), userChannel.getUserId(), CardEnum.MINGGANG);
                }
                return new MahjongCardBarEntity(CardEnum.MINGGANG, cardId);
            }
        }
        return null;
    }
}
